package com.flute.haflute.tools;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.jdom.JDOMException;

import com.flute.haflute.agent.AgentContext;
import com.flute.haflute.common.ClusterConfLoader;
import com.flute.haflute.common.ClusterConstants.ROLE;
import com.flute.haflute.common.ClusterContext;
import com.flute.haflute.jobbox.base.RunProcessInterface;
import com.flute.haflute.jobbox.common.CloudConstants;
import com.flute.haflute.jobbox.common.CloudContext;
import com.flute.haflute.jobbox.common.CloudInfoLoader;
import com.flute.haflute.jobbox.common.RunProcessLauncher;
import com.flute.haflute.jobbox.processes.Param;
import com.flute.haflute.jobbox.processes.Process;
import com.flute.haflute.jobbox.processes.Processes;

/**
 * 集群工具类
 * 
 */
public class ClusterUtils {
	private static String configFile = "conf/third-part-conf.xml";
	private static Properties props3rdPart = null;
	private static boolean isSystemShuttingDown = false;
	private static int exitCode = 100;

	public static synchronized void exitGracefully() {
		if (isSystemShuttingDown)
			return;

		isSystemShuttingDown = true;
		System.exit(exitCode);
	}

	/**
	 * 初始化子节点系统、软件和平台环境
	 * 
	 * @throws IOException
	 * @throws JDOMException
	 */
	public static void loadDefaultConfiguration() throws JDOMException,
			IOException {
		ClusterConfLoader.loadGlobalContext();
		new CloudInfoLoader().load();
	}

	/**
	 * 启动系统之外配置的后台服务
	 * 
	 * @param params
	 *            控制台参数
	 * @throws FileNotFoundException
	 * @throws InstantiationException
	 * @throws Exception
	 */
	public static void startCustomedBackends(String[] params)
			throws FileNotFoundException, InstantiationException, Exception {
		InputStream inputsteam = new FileInputStream(CloudContext.getRootDir()
				+ CloudConstants.CUSTOM_PROCESSES_FILENAME);
		Processes processes = ParseXMLUtil.getProcessesFromXML(inputsteam);
		List<Process> processList = processes.getProcesses();
		if (processList == null)
			return;
		int size = processList.size();
		List<RunProcessInterface> runProcesses = new ArrayList<RunProcessInterface>(
				size);
		List<String> paramsTemp = new ArrayList<String>(size);

		// 把后台进程都加入到运行的缓存中
		for (Process process : processList) {
			String needRole = process.getRole();
			if (!moveOn(needRole)) {
				continue;
			}
			for (Param param : process.getParams()) {
				paramsTemp.add(param.getValue());
			}
			paramsTemp.toArray(params);
			RunProcessInterface runProcess = process.getClz().newInstance();
			runProcess.callMain(params);
			runProcesses.add(runProcess);
			RunProcessLauncher.addRunProcess2Cache(runProcess);
		}

		// 监控是否所有的后台线程都起来了
		int initialized = 0;
		while (initialized < runProcesses.size()) {
			for (int i = 0; i < runProcesses.size(); i++) {
				if (runProcesses.get(i).isInitialized()) {
					initialized++;
					System.out.println("process ["
							+ runProcesses.get(i).getClass().getSimpleName()
							+ "] started OK");
				}
			}
			doWait();
		}
	}

	private static boolean moveOn(String needRole) {
		final String DM_OR_BDM = "DMorBDM";
		final String BDM_ONLY = "Only_BDM";
		final String AT_LEAST_EM = "Request_EM";
		final String EM_ONLY = "Only_EM";
		final String SLAVE_ONLY = "Only_Slave";
		final String ALL = "All";

		boolean ret = false;

		if (needRole == null && AgentContext.getNodeRole() == ROLE.DM) {
			ret = true;
		} else if (DM_OR_BDM.equalsIgnoreCase(needRole)
				&& (AgentContext.getNodeRole() == ROLE.DM || AgentContext
						.getNodeRole() == ROLE.BDM)) {
			ret = true;
		} else if (AT_LEAST_EM.equalsIgnoreCase(needRole)
				&& (AgentContext.getNodeRole() == ROLE.DM
						|| AgentContext.getNodeRole() == ROLE.BDM || AgentContext
						.getNodeRole() == ROLE.SM)) {
			ret = true;
		} else if (BDM_ONLY.equalsIgnoreCase(needRole)
				&& AgentContext.getNodeRole() == ROLE.BDM) {
			ret = true;
		} else if (EM_ONLY.equalsIgnoreCase(needRole)
				&& AgentContext.getNodeRole() == ROLE.SM) {
			ret = true;
		} else if (SLAVE_ONLY.equalsIgnoreCase(needRole)
				&& AgentContext.getNodeRole() == ROLE.SLAVE) {
			ret = true;
		} else if (ALL.equalsIgnoreCase(needRole)) {
			ret = true;
		}

		return ret;
	}

	/** 判断以参数dMorBDM表示的主机是否本机 */
	public static boolean isLocalNode(String dMorBDM) {
		InetAddress address = ClusterContext.getLocalAddress();
		if (dMorBDM.equalsIgnoreCase("localhost")
				|| dMorBDM.equalsIgnoreCase("127.0.0.1")
				|| dMorBDM.equalsIgnoreCase(address.getHostAddress())
				|| dMorBDM.equalsIgnoreCase(address.getHostName())) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 让当前占用CPU的线程等待200毫秒
	 */
	public static void doWait() {
		try {
			Thread.sleep(200L);
		} catch (Exception e) {
		}
	}

	/**
	 * 配置log4j日志参数
	 * 
	 * @param logConfigFile
	 */
	public static void configLogger(String logConfigFile) {
		org.apache.log4j.PropertyConfigurator.configure(ClusterContext
				.getRootDir() + logConfigFile);
	}

	public static synchronized Properties get3rdPartConfiguration()
			throws Exception {
		if (props3rdPart == null) {
			props3rdPart = new Properties();
			props3rdPart.loadFromXML(new FileInputStream(ClusterContext
					.getRootDir() + configFile));
		}
		return props3rdPart;
	}
}
